#include <e32svr.h>
#include <e32math.h>
#include <apgtask.h>
#include <S32FILE.H>
#include <W32STD.H>
#include <Etel3rdParty.h>

#include "ActivityTimer.h"
#include "Utils.h"

#include "clientservercommon.h"
#include "Observer.h"
#include "ObserverSession.h"
#include "Logger.h"

#include "Uids.h"
#include "APGWGNAM.H"


CMyServer::CMyServer(TInt aPriority)
:   CServer2(aPriority)
{
}

CMyServer::~CMyServer()
{
	iFs.Close();
	iKeyLock.Close();
	delete iActivityTimer;
	delete iAutoStopTimer;
}


CMyServer* CMyServer::NewLC()
{
	CMyServer* timeServer = new (ELeave) CMyServer(EPriorityNormal);
    CleanupStack::PushL(timeServer);
    timeServer->ConstructL();
    return timeServer;
}

void CMyServer::ConstructL()
{
LOG_BEGIN("CMyServer::ConstructL");
	StartL(KServerName);
	iFs.Connect();
	RProcess proc;
	iFs.SetSessionPath(proc.FileName().Left(2));
	iActivityTimer = CActivityTimer::NewL(*this);
	iKeyLock.Connect();
	ReloadSettings();

	iAutoStopTimer = CPeriodic::NewL( 0 );
	TTimeIntervalMicroSeconds32 tenSeconds( 10000000 ); 
	iAutoStopTimer->Start( tenSeconds, tenSeconds, TCallBack( CMyServer::AutoStopTimerTimeOut, this ) );

LOG_END("CMyServer::ConstructL");
}

void CMyServer::ReloadSettings()
{
	iAutoLockSettings.LoadSettingsL();
	iActivityTimer->WaitInactivity(iAutoLockSettings.iTimeOut.Int());
}

TInt CMyServer::AutoStopTimerTimeOut( TAny* aObj )
{
	static_cast< CMyServer* >( aObj )->StopServerIfNoSessionsAndDisabled();
	return KErrNone;
}

void CMyServer::StopServerIfNoSessionsAndDisabled()
{
	if (iSessionCount <= 0 && !iAutoLockSettings.iAutoLockEnabled )
	{
		LOG_WRITE("Stop the server");
		CActiveScheduler::Stop();
	}
}


CSession2* CMyServer::NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const
{
	// Check we're the right version
	if (!User::QueryVersionSupported(TVersion(KTimeServMajorVersionNumber,
                                              KTimeServMinorVersionNumber,
                                              KTimeServBuildVersionNumber),
									aVersion))
	{
		User::Leave(KErrNotSupported);
	}

	// Make new session
	return CMySession::NewL(*const_cast<CMyServer*> (this));
}


void CMyServer::IncrementSessions()
{
	iSessionCount++;
}

void CMyServer::DecrementSessions()
{
	iSessionCount--;
	StopServerIfNoSessionsAndDisabled();
}

void CMyServer::ThreadFunctionL()
{// Construct active scheduler
	CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
	CleanupStack::PushL(activeScheduler) ;//+activeScheduler
	CActiveScheduler::Install(activeScheduler);
// Construct our server
	CMyServer::NewLC();//+mySvr
	RProcess::Rendezvous(KErrNone);
	CActiveScheduler::Start();

	CleanupStack::PopAndDestroy(2);    //  -mySvr,  activeScheduler
}

TInt CMyServer::ThreadFunction()
{
	CTrapCleanup* cleanupStack = CTrapCleanup::New();
	if (!cleanupStack)
	{
		return KErrNoMemory;
	}

	TRAPD(err, ThreadFunctionL());
	if (err != KErrNone)
	{
		return err;
	}

	delete cleanupStack;
	cleanupStack = NULL;

	return KErrNone;
}

TInt E32Main()
{
	return CMyServer::ThreadFunction();
}
TBool LinesIdle()
{
#ifdef __WINS__
	return ETrue;
#else
	CTelephony::TCallStatusV1 status;
	CTelephony::TCallStatusV1Pckg statusPckg(status);

	CTelephony* telephony = CTelephony::NewL();
	TInt err = telephony->GetLineStatus(CTelephony::EVoiceLine, statusPckg);
	delete telephony;

	if (err == KErrNone)
	{
		status = statusPckg();
		return status.iStatus <= CTelephony::EStatusIdle;
	}
	else
	{
		return ETrue;
	}
#endif
}

void CMyServer::LockKeypadL()
{
LOG_FORMAT(_L("Auto lock %d"), iAutoLockSettings.iAutoLockEnabled);
	if (EFalse == iAutoLockSettings.iAutoLockEnabled)
		return ;
	RWsSession wsSession;
	wsSession.Connect();
	TInt groupId = wsSession.GetFocusWindowGroup();
	CApaWindowGroupName* groupName = CApaWindowGroupName::NewL(wsSession, groupId);
	TUid taskUid = groupName->AppUid();
LOG_FORMAT(_L("app uid 0x%08x (%d) [%S]"), taskUid, groupId, &groupName->WindowGroupName());
	delete groupName;

	if (iAutoLockSettings.iLockWhenIdle)
	{
#ifdef __WINS__
		if (taskUid.iUid != 0x208C0128 && taskUid.iUid != 0x208C11EC)
#else
		if (taskUid.iUid != 0x101fd64c && taskUid.iUid != 0x102750f0 )
#endif
			return ;
			
	}
	else if (iAutoLockSettings.iAppList.Count() > 0)
	{
		if (iAutoLockSettings.iAppList.Find(taskUid) != KErrNotFound)
			return ;
	}

//get profileId
	if (iAutoLockSettings.iCustomProfiles )
	{
		TInt profileId = Utils::GetActiveProfileId();
		if( iAutoLockSettings.iProfileList.Find(profileId) == KErrNotFound )
		{//profile not found
			return ;
		}
	}

	if (LinesIdle())
	{
		LOG_WRITE("Enable key lock");
		iKeyLock.EnableKeyLock();
	}
}
void CMyServer::NotifyInactivityL()
{
	LockKeypadL();
	iActivityTimer->WaitInactivity(iAutoLockSettings.iTimeOut.Int());
}
